import { addClass, removeClass } from 'zui/src/utils/dom'

// 实现一个包装类，专门用于在 h 函数中为 on 属性赋值实现事件绑定
class Transition {
  beforeEnter(el) {
    addClass(el, 'collapse-transition')
    if (!el.dataset) el.dataset = {}

    el.dataset.oldPaddingTop = el.style.paddingTop
    el.dataset.oldPaddingBottom = el.style.paddingBottom

    el.style.height = '0'
    el.style.paddingTop = 0
    el.style.paddingBottom = 0
  }

  enter(el) {
    el.dataset.oldOverflow = el.style.overflow
    if (el.scrollHeight !== 0) {
      el.style.height = el.scrollHeight + 'px'
      el.style.paddingTop = el.dataset.oldPaddingTop
      el.style.paddingBottom = el.dataset.oldPaddingBottom
    } else {
      el.style.height = ''
      el.style.paddingTop = el.dataset.oldPaddingTop
      el.style.paddingBottom = el.dataset.oldPaddingBottom
    }

    el.style.overflow = 'hidden'
  }

  afterEnter(el) {
    // for safari: remove class then reset height is necessary
    removeClass(el, 'collapse-transition')
    el.style.height = ''
    el.style.overflow = el.dataset.oldOverflow
  }

  beforeLeave(el) {
    if (!el.dataset) el.dataset = {}
    el.dataset.oldPaddingTop = el.style.paddingTop
    el.dataset.oldPaddingBottom = el.style.paddingBottom
    el.dataset.oldOverflow = el.style.overflow

    el.style.height = el.scrollHeight + 'px'
    el.style.overflow = 'hidden'
  }

  leave(el) {
    if (el.scrollHeight !== 0) {
      // for safari: add class after set height, or it will jump to zero height suddenly, weired
      addClass(el, 'collapse-transition')
      el.style.height = 0
      el.style.paddingTop = 0
      el.style.paddingBottom = 0
    }
  }

  afterLeave(el) {
    removeClass(el, 'collapse-transition')
    el.style.height = ''
    el.style.overflow = el.dataset.oldOverflow
    el.style.paddingTop = el.dataset.oldPaddingTop
    el.style.paddingBottom = el.dataset.oldPaddingBottom
  }
}

export default {
  name: 'ZCollapseTransition',

  // 表明这个组件是一个函数式组件
  // 函数式组件无状态即没有响应式数据，也没有实例即 this 上下文
  // https://v2.cn.vuejs.org/v2/api/#functional
  // https://v2.cn.vuejs.org/v2/guide/render-function.html#%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BB%84%E4%BB%B6
  functional: true,

  // 如果是函数式组件，第二个参数为 context: RenderContext
  // export interface RenderContext<Props=DefaultProps> {
  //   props: Props;  // 提供所有的 prop 的对象
  //   children: VNode[];
  //   slots(): any;
  //   data: VNodeData;
  //   parent: Vue;  // 父组件实例
  //   listeners: { [key: string]: Function | Function[] }; // 父组件实例的事件监听
  //   scopedSlots: { [key: string]: NormalizedScopedSlot }; // 父组件实例的作用域插槽
  //   injections: any // 父组件实例的注入
  // }

  // 这为什么使用 children 而不是插槽？
  // 因为这里 z-collapse-transition 组件只是纯粹为了实现过渡效果，不需要区分插槽类型
  // children 直接包含了所有子节点
  render(h, { children }) {
    // 原来 transition 组件本身支持通过绑定事件的方式实现动画
    // https://v2.cn.vuejs.org/v2/guide/transitions.html#JavaScript-%E9%92%A9%E5%AD%90
    const data = {
      // 这个写法可以学习，单独实现一个类用于事件绑定
      on: new Transition()
    }

    // 这里想真正弄懂这个组件，需要熟悉下 transition 和内部原理
    // https://v2.cn.vuejs.org/v2/api/#transition
    // https://v2.cn.vuejs.org/v2/guide/transitions.html
    return h('transition', data, children)
  }
}
